#include "proc.h"

static struct queue {
    int max_num;
    int in_num;
    int head;
    int rear;
    struct proc *procs[MAX_PROC_NUM];
} proc_queue;

void queue_init(struct queue *queue) {
    int i;
    queue->max_num = MAX_PROC_NUM;
    queue->in_num = 0;
    queue->head = 0;
    queue->rear = 0;
    for (i = 0; i < MAX_PROC_NUM; ++i) {
        queue->procs[i] = NULL;
    }
}

int isempty(struct queue *queue) {
	return queue->in_num == 0;
}

int isfull(struct queue *queue) {
    return (queue->max_num == queue->in_num);
}

void enqueue(struct queue *queue, struct proc *proc_in) {
    queue->procs[queue->rear] = proc_in;
    queue->in_num++;
    queue->rear = (queue->rear + 1) % queue->max_num;
}

struct proc *dequeue(struct queue *queue) {
	if (isempty(queue)) {
		return NULL;
	}
    struct proc *proc_out = queue->procs[queue->head];
    queue->procs[queue->head] = NULL;
    queue->in_num--;
    queue->head = (queue->head + 1) % queue->max_num;
    return proc_out;
}

void sche_init() {
	queue_init(&proc_queue);
}

/* @brief: choose the next proc from head of the queue to run
 */
struct proc *next_proc() {
	if (cur_proc != init_proc) {
		enqueue(&proc_queue, cur_proc);
	}
	return dequeue(&proc_queue);
}

/* @brief: add a proc into the waiting queue
 * @param proc_in: added proc
 */
void runnable(struct proc *proc_in) {
	enqueue(&proc_queue, proc_in);
}

struct scheduler sche_fifo = {
	.init = sche_init,
	.next_proc = next_proc,
	.runnable = runnable,
};

